package cn.piesat.scanning.business.common.algorithm.ftpScan;

import com.alibaba.fastjson.JSON;
import cn.piesat.scanning.business.common.AlgorithmDefineAbstract;
import cn.piesat.scanning.dto.HtPathConfigurationDTO;
import cn.piesat.scanning.dto.HtScanningMetadataDTO;
import cn.piesat.scanning.dto.HtScheduleJobDTO;
import cn.piesat.scanning.service.DbDmsSchedulerTaskFileRecordService;
import cn.piesat.scanning.service.HtPathConfigurationService;
import cn.piesat.scanning.service.HtScanningMetadataService;
import cn.piesat.scanning.service.HtScheduleJobService;
import cn.piesat.scanning.utils.FTPUtil;
import cn.piesat.scanning.utils.FileUtil;
import cn.piesat.scanning.utils.MatchTime;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author xhl
 */
public abstract class FtpScanAbstract extends AlgorithmDefineAbstract {

    private static final Logger logger = LoggerFactory.getLogger(FtpScanAbstract.class);
    @Autowired
    private HtScheduleJobService htScheduleJobService;
    @Autowired
    private HtPathConfigurationService htPathConfigurationService;
    @Autowired
    private HtScanningMetadataService htScanningMetadataService;
    @Autowired
    private DbDmsSchedulerTaskFileRecordService dbDmsSchedulerTaskFileRecordService;

    @Override
    public void exec(Map<String, Object> params, String taskId) {
        FtpScanParams ftpScanParams = JSON.parseObject(JSON.toJSONString(params), FtpScanParams.class);
        HtScheduleJobDTO taskDTO = htScheduleJobService.findById(taskId);
        HtPathConfigurationDTO pathDTO = htPathConfigurationService.findById(taskDTO.getPathConfigId());
//        List<String> dirPath = processParams(pathDTO, ftpScanParams);
        String scanningPath = pathDTO.getScanningPath();
        List<FtpScanAlgPath> ftpScanAlgPaths = listFtpFile(scanningPath, pathDTO, ftpScanParams,taskId);
//        List<String> fileNameListByTaskId = dbDmsSchedulerTaskFileRecordService.findFileNameListByTaskId(taskId);
        downloadFile(ftpScanAlgPaths,pathDTO,taskDTO,ftpScanParams,taskId);
    }

    private List<FtpScanAlgPath> listFtpFile(String path, HtPathConfigurationDTO pathDTO,
                                             FtpScanParams params,String taskId) {
        List<FtpScanAlgPath> pojoList = new ArrayList<>();
        String ip = params.getIp();
        String name = params.getName();
        Integer port = params.getPort();
        String pwd = params.getPwd();
        FTPUtil ftpUtil = new FTPUtil();
        FTPClient ftpClient = null;
        try{
            ftpClient = ftpUtil.getFTPClient(ip,port,name,pwd);
//            Set<String> metadataSet = htScanningMetadataService.listByDate(params.getStartTime(), params.getEndTime());
            List<String> fileNameListByTaskId = dbDmsSchedulerTaskFileRecordService.findFileNameListByTaskId(taskId);
            recursionScanningFtpFile(ftpClient,path,pathDTO,params,pojoList,fileNameListByTaskId);
        }catch (Exception e) {
            logger.error("FTP扫描出现异常,ip:{},{}",ip,e.getMessage());
        }finally {
            ftpUtil.closeFTP(ftpClient);
        }
        return pojoList;
    }

   public static void is(String dirPath){
        File file = new File(dirPath);
        File[] files = file.listFiles();
        for (int i = 0; i < files.length; i++) {
            if (files[i].isDirectory()&& !files[i].getName().matches("\\.+") ) {
//                    if (files[i].isDirectory() && !files[i].getName().matches("\\.+")) {
                System.out.println(files[i].getName());
                System.out.println("fileName"+files[i].getName());
                String newScanPath = (dirPath + File.separator + files[i].getName()).replaceAll("/+","/");
                System.out.println("newScanPath"+newScanPath);
                is(newScanPath);
            }else if (files[i].isFile()){
                System.out.println("1111111");
            }
        }
    }


    public static void main(String[] args) {
        FTPUtil ftpUtil = new FTPUtil();

        FTPClient ftpClient = ftpUtil.getFTPClient("ftp.nsmc.org.cn", 21, "PNQ", "NSMC_NQ7412");
        ftpUtil.downLoadFTP(ftpClient,"/FY3D_NDVI/20220110/EAST","FY3D_MERSI_EAST_L3_NVI_MLT_GLL_20220110_AOTD_1000M_MS.LDF","D:\\Work");
        ftpUtil.closeFTP(ftpClient);
//        String dirPath = "D:\\NDVI";


//        Pattern p = Pattern.compile(".*LDF.*|.*hdr");
//        Matcher matcher = p.matcher("FY3D_MERSI_WEST_L3_NVI_MLT_GLL_20221120_AOTD_1000M_MS.LDF.aux.xml");
//        System.out.println(matcher.matches());
//        // 1.旬数据查询 10、20、31
//        String lastDate = DateUtil.lastDayOfMonth("yyyyMMdd");
//        String firstDate = lastDate.substring(0, 6) + "10";
//        String secondDate = lastDate.substring(0, 6) + "20";
//        String preLastDate = DateUtil.lastDayOfPreMonth("yyyyMMdd");
//
//        System.out.println();
//        System.out.println();
//
//
//
//        String dirPath = "20221010";
//        String aaa = "20221110";
//        System.out.println(StrUtil.compare(dirPath,aaa, true));
//
//        System.out.println(dirPath.replaceAll("/+","/"));

    }


    private void recursionScanningFtpFile(FTPClient ftpClient,String dirPath,HtPathConfigurationDTO pathDTO,
                                          FtpScanParams params,List<FtpScanAlgPath> pojoList,
                                          List<String> fileNameListByTaskId) {

        System.out.println("dirPath"+dirPath);
        String fileNamePattern = params.getFileNamePattern();
        String fileDatePattern = params.getFileDatePattern();
        String start = params.getStartTime();
        String end = params.getEndTime();

        int subLength = start.length();
//        long s = Long.parseLong(start);
//        long e = Long.parseLong(end);
        Pattern p = Pattern.compile(fileNamePattern);
        if (StringUtils.isNotEmpty(dirPath)) {
            try {
                ftpClient.changeWorkingDirectory(new String(dirPath.getBytes("UTF-8"),"ISO-8859-1"));
                ftpClient.enterLocalPassiveMode();
                FTPFile files[] = ftpClient.listFiles();
                for (int i = 0; i < files.length; i++) {

                    if (files[i].isDirectory() )  {
//                        dbDmsSchedulerTaskFileRecordService.findByTaskIdAndFileName();
                        String newScanPath = (dirPath + File.separator + files[i].getName()).replaceAll("/+","/");
                        recursionScanningFtpFile(ftpClient,newScanPath,pathDTO,params,pojoList,fileNameListByTaskId);
                    }else if (files[i].isFile()){
                        logger.info("递归文件并进入解析方法!!!");
                        String fileName = files[i].getName();
                        Matcher matcher = p.matcher(fileName);
                        if(matcher.matches()) {
//                                //数据库中是否存在
                                if (!fileNameListByTaskId.contains(fileName)) {
                                    FtpScanAlgPath ftpScanAlgPath = new FtpScanAlgPath();
                                    ftpScanAlgPath.setFileName(fileName);
                                    ftpScanAlgPath.setFilePath(dirPath);
                                    String ftpPath = dirPath.substring(pathDTO.getScanningPath().length());
                                    String newLocalPath = pathDTO.getOutputPath() + File.separator + ftpPath.substring(0,4)+File.separator+ ftpPath;
                                    System.out.println("newLocalPath = " + newLocalPath);
                                    System.out.println("dirPathSSSS"+dirPath.substring(pathDTO.getScanningPath().length()));
                                    ftpScanAlgPath.setNewLocalPath(newLocalPath);
                                    pojoList.add(ftpScanAlgPath);
                                }
//                            }
                        }
                    }
                }
            }catch (Exception ex) {
                logger.error("ftp list files exception {}", ex.getLocalizedMessage(),ex);
            }
        }
    }

    private void downloadFile(List<FtpScanAlgPath> pojoList, HtPathConfigurationDTO pathDTO, HtScheduleJobDTO taskDTO, FtpScanParams params,String taskId) {
        logger.info("进入downloadFile方法!!!");
        String ip = params.getIp();
        String name = params.getName();
        Integer port = params.getPort();
        String pwd = params.getPwd();
        FTPUtil ftpUtil = new FTPUtil();
        FTPClient ftpClient = null;
        try {
            ftpClient = ftpUtil.getFTPClient(ip,port,name,pwd);
            List<String> fileNameList = pojoList.stream().map(FtpScanAlgPath::getFileName).collect(Collectors.toList());
            dbDmsSchedulerTaskFileRecordService.prepareDataByFileNameList(taskDTO.getId(),fileNameList);
            for (FtpScanAlgPath ftpScanAlgPath : pojoList) {
                dbDmsSchedulerTaskFileRecordService.dataExecution(taskDTO.getId(),ftpScanAlgPath.getFileName());
                logger.info("下载文件：{}",ftpScanAlgPath.getFilePath()+File.separator+ftpScanAlgPath.getFileName());
                long t1 = System.currentTimeMillis();
                boolean downLoadFTP = ftpUtil.downLoadFTP(ftpClient, ftpScanAlgPath.getFilePath(),ftpScanAlgPath.getFileName(),ftpScanAlgPath.getNewLocalPath());
                if (downLoadFTP) {
                    logger.info("文件存储位置：{}", pathDTO.getOutputPath());
                    logger.info("[{}]下载完成，耗时:{}秒", ftpScanAlgPath.getFilePath()+File.separator+ftpScanAlgPath.getFileName(), (System.currentTimeMillis() - t1) / 1000);
                    dbDmsSchedulerTaskFileRecordService.dataResults(taskId,ftpScanAlgPath.getFileName(),true);
                } else {
                    logger.info("下载文件失败：{}",ftpScanAlgPath.getFilePath()+File.separator+ftpScanAlgPath.getFileName());
                    dbDmsSchedulerTaskFileRecordService.dataResults(taskDTO.getId(),ftpScanAlgPath.getFileName(),false);
                }
            }
        }finally {
            if (ftpClient != null) {
                ftpUtil.closeFTP(ftpClient);
            }
        }
    }

    public abstract HtScanningMetadataDTO splitName(File file, HtPathConfigurationDTO pathDTO);

    /**
     * 处理输入参数
     * @param pathDTO 路径实体类，获取扫描路径和输出路径
     * @param ftpScanParams 要处理的参数（开始时间、结束时间、目录匹配规则、最近多少分钟）
     */
    protected List<String> processParams(HtPathConfigurationDTO pathDTO, FtpScanParams ftpScanParams) {
        String scanningPath = pathDTO.getScanningPath();
        String startTime = ftpScanParams.getStartTime();
        String endTime = ftpScanParams.getEndTime();
        String lately = ftpScanParams.getLately();
//        String dirPathRule = ftpScanParams.getDirPathRule();
        String dirPathRule = "";
        List<String> dirPath = new ArrayList<>();
        //如果扫描路径为空，则数据扫描自定义算法不继续执行
        if (StringUtils.isNotEmpty(scanningPath)) {
            //填入开始时间和最近多少分钟的两种情况，优先填入开始时间参数
            if (StringUtils.isNotEmpty(startTime)) {
                ftpScanParams.setStartTime(conventDateTimeFormat(startTime));
                ftpScanParams.setEndTime(conventDateTimeFormat(endTime));
                String completePathRule = scanningPath + File.separator + dirPathRule;
                if(checkBraces(scanningPath)) {
//                    dirPath = getDirPath(completePathRule,dayList,ftpScanParams)
//                            .stream().distinct().collect(Collectors.toList());
                    List<Date> dayList = getTimeZones(ftpScanParams.getStartTime(), ftpScanParams.getEndTime());
                    for (Date date : dayList) {
                        String pathByDate = FileUtil.getPathByDate(completePathRule,date);
                        dirPath.add(pathByDate);
                    }
                }else{
                    dirPath = new ArrayList<>();
                    dirPath.add(completePathRule);
                }
            } else if (StringUtils.isNotEmpty(lately)) {
                long late = Long.parseLong(lately);
                DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMddHHmm");
                ftpScanParams.setStartTime(LocalDateTime.now().minusMinutes(late).format(df));
                ftpScanParams.setEndTime(LocalDateTime.now().format(df));
                String completePathRule = scanningPath + File.separator + dirPathRule;
                if(checkBraces(dirPathRule)) {
                    String pathByDate = FileUtil.getPathByDate(completePathRule,new Date());
                    dirPath.add(pathByDate);
                }else{
                    dirPath.add(completePathRule);
                }
            }
        }
        return dirPath;
    }

    public List<String> getDirPath(String dirPath, List<Date> dateList, FtpScanParams params) {
        List<String> dirList = new ArrayList<>();
        FTPUtil ftpUtil = null;
        FTPClient ftpClient = null;
        //ip地址
        String ip = params.getIp();
        //端口
        Integer port = params.getPort();
        //用户名
        String name = params.getName();
        //密码
        String pwd = params.getPwd();
        try{
            ftpUtil = new FTPUtil();
            ftpClient = ftpUtil.getFTPClient(ip, port, name, pwd);
            for (int i = 0; i < dateList.size(); i++) {
                String pathByDate = FileUtil.getPathByDate(dirPath, dateList.get(i));
                if (ftpUtil.ftpExists(pathByDate,ftpClient)) {
                    dirList.add(pathByDate);
                }
            }
        }catch (Exception e) {
            logger.error("FTP扫描时FTPClient异常{}",e.getMessage());
        }finally {
            if (null != ftpClient){
                ftpUtil.closeFTP(ftpClient);
            }
        }
        return dirList;
    }

    /**
     * 根据正则匹配获取到日期，如果小于12位则补0
     * @param fileName
     * @param dataFilePattern
     * @return
     */
    private String getDateTimeStr(String fileName,String dataFilePattern){
        String str = "";
        if(dataFilePattern != null && !"".equals(dataFilePattern)){
            Pattern p = Pattern.compile(dataFilePattern);
            Matcher m = p.matcher(fileName);
            boolean result = m.find();
            while (result){
                str = m.group(0);
                break;
            }
        }
        if(str.length() < 12){
            int leftlenth = 12 - str.length();
            for(int i = 0 ; i < leftlenth ; i++){
                str += "0";
            }
        }
        return str;
    }

    /**
     * 判断字符串中是否存在 {}
     * @param path
     * @return boolean
     */
    private boolean checkBraces(String path) {
        String leftBraces = "{";
        return path.contains(leftBraces);
    }

    /**
     * 格式化时间
     * @param string
     * @return String datetime
     */
    private String conventDateTimeFormat(String string){
        String dateTime = "";
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        DateTimeFormatter df1 = DateTimeFormatter.ofPattern("yyyyMMdd");
        //判断是否为空,空的情况直接获取当前时间 格式 yyyyMMdd
        if(StringUtils.isEmpty(string)) {
            dateTime = LocalDateTime.now().format(df1);
            return dateTime;
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");

        try {
            //格式为 '{yyyy+-}{MM+-}{dd+-}{HH+-}{mm+-}{ss+-}'
            if(checkBraces(string)) {
                Date date = MatchTime.getDate(new Date(), string);
                dateTime = sdf.format(date);
            }else {
                dateTime = LocalDateTime.parse(string, df).format(df1);
            }
        } catch ( Exception e){
            e.printStackTrace();
        }
        return dateTime;
    }

    /**
     * 获取时间区间中所有的天
     * @param startTime
     * @param endTime
     * @return List<Date>
     */
    private List<Date> getTimeZones(String startTime, String endTime){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        List<Date> list = new ArrayList<Date>();
        try {
            Date startDate = sdf.parse(startTime);
            Date endDate = sdf.parse(endTime);
            for (long i = (startDate.getTime()-(24*60*60*1000)); i < endDate.getTime(); i++) {
                i += (24*60*60*1000);
                Date date = new Date();
                date.setTime(i);
                list.add(date);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return list;
    }

}
